#include <iostream>
#include <string>
#include <memory>
#include <unordered_map>
#include "../../third_part/Muduo/muduo/examples/protobuf/codec/codec.h"
#include "../../third_part/Muduo/muduo/examples/protobuf/codec/dispatcher.h"
#include "./request.pb.h"
#include "../../third_part/Muduo/build/release-install-cpp11/include/muduo/base/Logging.h"
#include "../../third_part/Muduo/build/release-install-cpp11/include/muduo/base/Mutex.h"
#include "../../third_part/Muduo/build/release-install-cpp11/include/muduo/net/EventLoop.h"
#include "../../third_part/Muduo/build/release-install-cpp11/include/muduo/net/TcpServer.h"
using namespace std;


class Server {
public :
    typedef shared_ptr<google::protobuf::Message> MessagePtr; 
    typedef shared_ptr<reqNs::TranslateRequest> _trans_req_ptr; // 操作request的智能指针
    typedef shared_ptr<reqNs::CalculateRequest> _cal_req_ptr;
    Server(int port)
        :_server(&_baseloop, muduo::net::InetAddress("0.0.0.0", port), "protobuf_server", muduo::net::TcpServer::kReusePort)
        ,_dispatcher(std::bind(&Server::OnUnkownMessage, this, placeholders:: _1, placeholders:: _2, placeholders:: _3))
        ,_codec(std::bind(&ProtobufDispatcher::onProtobufMessage, &_dispatcher, placeholders:: _1, placeholders:: _2, placeholders:: _3))
    {
        // 注册请求处理函数
        _dispatcher.registerMessageCallback<reqNs::TranslateRequest>(std::bind(&Server::OnTranslate, this, placeholders::_1, placeholders::_2, placeholders::_3));
        _dispatcher.registerMessageCallback<reqNs::CalculateRequest>(std::bind(&Server::OnCalculate, this, placeholders::_1, placeholders::_2, placeholders::_3));
        _server.setMessageCallback(std::bind(&ProtobufCodec::onMessage, &_codec, placeholders::_1, placeholders::_2, placeholders::_3));
        _server.setConnectionCallback(std::bind(&Server::OnConnection, this, placeholders::_1));
        _dict = {
            {"hello", "你好"},
            {"left", "左边"},
            {"right", "右边"},
            {"answer", "答案"},
            {"apple", "苹果"}
        };

    }
    // 通信连接收到请求时的回调函数
    string translate(string& str) {
        auto it = _dict.find(str);
        if (it == _dict.end()) {
            return "不知道!";
        }
        return it->second;
    }

    pair<int, int> Cal(int x, int y, string op) {
        int result = 0;
        int code = 0;
        if (op == "+") {
            result = x + y;
        } else if (op == "-") {
            result = x - y;
        } else if (op == "*") {
            result = x * y;
        } else if (op == "/") {
            if (y == 0) {
                result = -1;
                code = -1;
            } else {
                result = x / y;
            }
        } else if (op == "%") {
            if (y == 0) {
                result = -1;
                code = -2;
            } else {
                result = x % y;
            }
        } else {
            result = -3;
            code = -3;
        }
        return { result, code };
    }


    void Start() {
        _server.start();
        _baseloop.loop();

    }

private :
    // 处理翻译的请求处理函数
    void OnTranslate(const muduo::net::TcpConnectionPtr& conn, const _trans_req_ptr& message, muduo::Timestamp) {
        // 1、提取message中的有效消息，也就是需要翻译的内容
        string req_msg = message->word();
        // 2、进行翻译，得到结果
        string resp_msg = translate(req_msg);   
        // 3、组织protobuf的响应
        reqNs::TranslateRequest req;
        
        reqNs::TranslateResponse resp;
        resp.set_answer(resp_msg);
        // // 对resp进行序列化
        // string send_message = resp.SerializeAsString();
        
        // 4、发送响应
        _codec.send(conn, resp);
    }

    // 处理计算器的处理函数
    void OnCalculate(const muduo::net::TcpConnectionPtr& conn, const _cal_req_ptr& message, muduo::Timestamp) {
        int x = message->x();
        int y = message->y();
        string op = message->op();
        pair<int, int> ret = Cal(x, y, op);
        reqNs::CalculateResponse resp;
        resp.set_result(ret.first);
        resp.set_code(ret.second);
        _codec.send(conn, resp);
    }
    // 未知请求的处理方法
    void OnUnkownMessage(const muduo::net::TcpConnectionPtr& conn, const MessagePtr& message, muduo::Timestamp) {
        conn->shutdown();

    }

    void OnConnection(const muduo::net::TcpConnectionPtr& conn) {
        if (conn->connected()) {
            LOG_INFO << "新连接建立成功!";
        } else {
            LOG_INFO << "链接已关闭";
        }

    }

    // void OnProtobufMessage() {
        
    // }
private :
    muduo::net::EventLoop _baseloop;
    muduo::net::TcpServer _server; // 服务器对象
    ProtobufDispatcher _dispatcher; // 请求分发器对象——要想其中注册请求处理函数的
    ProtobufCodec _codec; // protobuf协议处理对象——针对收到的请求数据进行protobuf处理
    unordered_map<string, string> _dict;
};


int main(int argc, char* args[]) {
    if (argc != 2) {
        cout << "Usage:\n\r" << args[0] << " local_port\n" << endl;
        return 0;
    }
    int port = stoi(args[1]);
    Server svr(port);
    svr.Start();
    return 0;
}

